/*
 * This file is part of the openHiTLS project.
 *
 * openHiTLS is licensed under the Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 *     http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
#include "hitls_build.h"
#ifdef HITLS_CRYPTO_BN_PRIME_RFC3526

#include "crypt_errno.h"
#include "bn_basic.h"

#if defined(HITLS_SIXTY_FOUR_BITS)

// RFC 3526: 2048-bit MODP GroupUL, this prime is: 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 }
static const BN_UINT RFC3526_PRIME_2048[] = {
    0xFFFFFFFFFFFFFFFFUL, 0x15728E5A8AACAA68UL, 0x15D2261898FA0510UL, 0x3995497CEA956AE5UL,
    0xDE2BCBF695581718UL, 0xB5C55DF06F4C52C9UL, 0x9B2783A2EC07A28FUL, 0xE39E772C180E8603UL,
    0x32905E462E36CE3BUL, 0xF1746C08CA18217CUL, 0x1C62F356208552BBUL, 0x83655D23DCA3AD96UL,
    0x69163FA8FD24CF5FUL, 0x98DA48361C55D39AUL, 0xC2007CB8A163BF05UL, 0x49286651ECE45B3DUL,
    0xAE9F24117C4B1FE6UL, 0xEE386BFB5A899FA5UL, 0x0BFF5CB6F406B7EDUL, 0xF44C42E9A637ED6BUL,
    0xE485B576625E7EC6UL, 0x4FE1356D6D51C245UL, 0x302B0A6DF25F1437UL, 0xEF9519B3CD3A431BUL,
    0x514A08798E3404DDUL, 0x020BBEA63B139B22UL, 0x29024E088A67CC74UL, 0xC4C6628B80DC1CD1UL,
    0xC90FDAA22168C234UL, 0xFFFFFFFFFFFFFFFFUL
};

// RFC 3526: 3072-bit MODP GroupUL, this prime is: 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 }
static const BN_UINT RFC3526_PRIME_3072[] = {
    0xFFFFFFFFFFFFFFFFUL, 0x4B82D120A93AD2CAUL, 0x43DB5BFCE0FD108EUL, 0x08E24FA074E5AB31UL,
    0x770988C0BAD946E2UL, 0xBBE117577A615D6CUL, 0x521F2B18177B200CUL, 0xD87602733EC86A64UL,
    0xF12FFA06D98A0864UL, 0xCEE3D2261AD2EE6BUL, 0x1E8C94E04A25619DUL, 0xABF5AE8CDB0933D7UL,
    0xB3970F85A6E1E4C7UL, 0x8AEA71575D060C7DUL, 0xECFB850458DBEF0AUL, 0xA85521ABDF1CBA64UL,
    0xAD33170D04507A33UL, 0x15728E5A8AAAC42DUL, 0x15D2261898FA0510UL, 0x3995497CEA956AE5UL,
    0xDE2BCBF695581718UL, 0xB5C55DF06F4C52C9UL, 0x9B2783A2EC07A28FUL, 0xE39E772C180E8603UL,
    0x32905E462E36CE3BUL, 0xF1746C08CA18217CUL, 0x670C354E4ABC9804UL, 0x9ED529077096966DUL,
    0x1C62F356208552BBUL, 0x83655D23DCA3AD96UL, 0x69163FA8FD24CF5FUL, 0x98DA48361C55D39AUL,
    0xC2007CB8A163BF05UL, 0x49286651ECE45B3DUL, 0xAE9F24117C4B1FE6UL, 0xEE386BFB5A899FA5UL,
    0x0BFF5CB6F406B7EDUL, 0xF44C42E9A637ED6BUL, 0xE485B576625E7EC6UL, 0x4FE1356D6D51C245UL,
    0x302B0A6DF25F1437UL, 0xEF9519B3CD3A431BUL, 0x514A08798E3404DDUL, 0x020BBEA63B139B22UL,
    0x29024E088A67CC74UL, 0xC4C6628B80DC1CD1UL, 0xC90FDAA22168C234UL, 0xFFFFFFFFFFFFFFFFUL
};

// RFC 3526: 4096-bit MODP GroupUL, this prime is: 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 }
static const BN_UINT RFC3526_PRIME_4096[] = {
    0xFFFFFFFFFFFFFFFFUL, 0x4DF435C934063199UL, 0x86FFB7DC90A6C08FUL, 0x93B4EA988D8FDDC1UL,
    0xD0069127D5B05AA9UL, 0xB81BDD762170481CUL, 0x1F612970CEE2D7AFUL, 0x233BA186515BE7EDUL,
    0x99B2964FA090C3A2UL, 0x287C59474E6BC05DUL, 0x2E8EFC141FBECAA6UL, 0xDBBBC2DB04DE8EF9UL,
    0x2583E9CA2AD44CE8UL, 0x1A946834B6150BDAUL, 0x99C327186AF4E23CUL, 0x88719A10BDBA5B26UL,
    0x1A723C12A787E6D7UL, 0x4B82D120A9210801UL, 0x43DB5BFCE0FD108EUL, 0x08E24FA074E5AB31UL,
    0x770988C0BAD946E2UL, 0xBBE117577A615D6CUL, 0x521F2B18177B200CUL, 0xD87602733EC86A64UL,
    0xF12FFA06D98A0864UL, 0xCEE3D2261AD2EE6BUL, 0x1E8C94E04A25619DUL, 0xABF5AE8CDB0933D7UL,
    0xB3970F85A6E1E4C7UL, 0x8AEA71575D060C7DUL, 0xECFB850458DBEF0AUL, 0xA85521ABDF1CBA64UL,
    0xAD33170D04507A33UL, 0x15728E5A8AAAC42DUL, 0x15D2261898FA0510UL, 0x3995497CEA956AE5UL,
    0xDE2BCBF695581718UL, 0xB5C55DF06F4C52C9UL, 0x9B2783A2EC07A28FUL, 0xE39E772C180E8603UL,
    0x32905E462E36CE3BUL, 0xF1746C08CA18217CUL, 0x670C354E4ABC9804UL, 0x9ED529077096966DUL,
    0x1C62F356208552BBUL, 0x83655D23DCA3AD96UL, 0x69163FA8FD24CF5FUL, 0x98DA48361C55D39AUL,
    0xC2007CB8A163BF05UL, 0x49286651ECE45B3DUL, 0xAE9F24117C4B1FE6UL, 0xEE386BFB5A899FA5UL,
    0x0BFF5CB6F406B7EDUL, 0xF44C42E9A637ED6BUL, 0xE485B576625E7EC6UL, 0x4FE1356D6D51C245UL,
    0x302B0A6DF25F1437UL, 0xEF9519B3CD3A431BUL, 0x514A08798E3404DDUL, 0x020BBEA63B139B22UL,
    0x29024E088A67CC74UL, 0xC4C6628B80DC1CD1UL, 0xC90FDAA22168C234UL, 0xFFFFFFFFFFFFFFFFUL
};

#elif defined(HITLS_THIRTY_TWO_BITS)

// RFC 3526: 2048-bit MODP Group, this prime is: 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 }
static const BN_UINT RFC3526_PRIME_2048[] = {
    0xFFFFFFFF, 0xFFFFFFFF, 0x8AACAA68, 0x15728E5A, 0x98FA0510, 0x15D22618, 0xEA956AE5, 0x3995497C,
    0x95581718, 0xDE2BCBF6, 0x6F4C52C9, 0xB5C55DF0, 0xEC07A28F, 0x9B2783A2, 0x180E8603, 0xE39E772C,
    0x2E36CE3B, 0x32905E46, 0xCA18217C, 0xF1746C08, 0x4ABC9804, 0x670C354E, 0x7096966D, 0x9ED52907,
    0x208552BB, 0x1C62F356, 0xDCA3AD96, 0x83655D23, 0xFD24CF5F, 0x69163FA8, 0x1C55D39A, 0x98DA4836,
    0xA163BF05, 0xC2007CB8, 0xECE45B3D, 0x49286651, 0x7C4B1FE6, 0xAE9F2411, 0x5A899FA5, 0xEE386BFB,
    0xF406B7ED, 0x0BFF5CB6, 0xA637ED6B, 0xF44C42E9, 0x625E7EC6, 0xE485B576, 0x6D51C245, 0x4FE1356D,
    0xF25F1437, 0x302B0A6D, 0xCD3A431B, 0xEF9519B3, 0x8E3404DD, 0x514A0879, 0x3B139B22, 0x020BBEA6,
    0x8A67CC74, 0x29024E08, 0x80DC1CD1, 0xC4C6628B, 0x2168C234, 0xC90FDAA2, 0xFFFFFFFF, 0xFFFFFFFF
};

// RFC 3526: 3072-bit MODP Group, this prime is: 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 }
static const BN_UINT RFC3526_PRIME_3072[] = {
    0xFFFFFFFF, 0xFFFFFFFF, 0xA93AD2CA, 0x4B82D120, 0xE0FD108E, 0x43DB5BFC, 0x74E5AB31, 0x08E24FA0,
    0xBAD946E2, 0x770988C0, 0x7A615D6C, 0xBBE11757, 0x177B200C, 0x521F2B18, 0x3EC86A64, 0xD8760273,
    0xD98A0864, 0xF12FFA06, 0x1AD2EE6B, 0xCEE3D226, 0x4A25619D, 0x1E8C94E0, 0xDB0933D7, 0xABF5AE8C,
    0xA6E1E4C7, 0xB3970F85, 0x5D060C7D, 0x8AEA7157, 0x58DBEF0A, 0xECFB8504, 0xDF1CBA64, 0xA85521AB,
    0x04507A33, 0xAD33170D, 0x8AAAC42D, 0x15728E5A, 0x98FA0510, 0x15D22618, 0xEA956AE5, 0x3995497C,
    0x95581718, 0xDE2BCBF6, 0x6F4C52C9, 0xB5C55DF0, 0xEC07A28F, 0x9B2783A2, 0x180E8603, 0xE39E772C,
    0x2E36CE3B, 0x32905E46, 0xCA18217C, 0xF1746C08, 0x4ABC9804, 0x670C354E, 0x7096966D, 0x9ED52907,
    0x208552BB, 0x1C62F356, 0xDCA3AD96, 0x83655D23, 0xFD24CF5F, 0x69163FA8, 0x1C55D39A, 0x98DA4836,
    0xA163BF05, 0xC2007CB8, 0xECE45B3D, 0x49286651, 0x7C4B1FE6, 0xAE9F2411, 0x5A899FA5, 0xEE386BFB,
    0xF406B7ED, 0x0BFF5CB6, 0xA637ED6B, 0xF44C42E9, 0x625E7EC6, 0xE485B576, 0x6D51C245, 0x4FE1356D,
    0xF25F1437, 0x302B0A6D, 0xCD3A431B, 0xEF9519B3, 0x8E3404DD, 0x514A0879, 0x3B139B22, 0x020BBEA6,
    0x8A67CC74, 0x29024E08, 0x80DC1CD1, 0xC4C6628B, 0x2168C234, 0xC90FDAA2, 0xFFFFFFFF, 0xFFFFFFFF
};

// RFC 3526: 4096-bit MODP Group, this prime is: 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 }
static const BN_UINT RFC3526_PRIME_4096[] = {
    0xFFFFFFFF, 0xFFFFFFFF, 0x34063199, 0x4DF435C9, 0x90A6C08F, 0x86FFB7DC, 0x8D8FDDC1, 0x93B4EA98,
    0xD5B05AA9, 0xD0069127, 0x2170481C, 0xB81BDD76, 0xCEE2D7AF, 0x1F612970, 0x515BE7ED, 0x233BA186,
    0xA090C3A2, 0x99B2964F, 0x4E6BC05D, 0x287C5947, 0x1FBECAA6, 0x2E8EFC14, 0x04DE8EF9, 0xDBBBC2DB,
    0x2AD44CE8, 0x2583E9CA, 0xB6150BDA, 0x1A946834, 0x6AF4E23C, 0x99C32718, 0xBDBA5B26, 0x88719A10,
    0xA787E6D7, 0x1A723C12, 0xA9210801, 0x4B82D120, 0xE0FD108E, 0x43DB5BFC, 0x74E5AB31, 0x08E24FA0,
    0xBAD946E2, 0x770988C0, 0x7A615D6C, 0xBBE11757, 0x177B200C, 0x521F2B18, 0x3EC86A64, 0xD8760273,
    0xD98A0864, 0xF12FFA06, 0x1AD2EE6B, 0xCEE3D226, 0x4A25619D, 0x1E8C94E0, 0xDB0933D7, 0xABF5AE8C,
    0xA6E1E4C7, 0xB3970F85, 0x5D060C7D, 0x8AEA7157, 0x58DBEF0A, 0xECFB8504, 0xDF1CBA64, 0xA85521AB,
    0x04507A33, 0xAD33170D, 0x8AAAC42D, 0x15728E5A, 0x98FA0510, 0x15D22618, 0xEA956AE5, 0x3995497C,
    0x95581718, 0xDE2BCBF6, 0x6F4C52C9, 0xB5C55DF0, 0xEC07A28F, 0x9B2783A2, 0x180E8603, 0xE39E772C,
    0x2E36CE3B, 0x32905E46, 0xCA18217C, 0xF1746C08, 0x4ABC9804, 0x670C354E, 0x7096966D, 0x9ED52907,
    0x208552BB, 0x1C62F356, 0xDCA3AD96, 0x83655D23, 0xFD24CF5F, 0x69163FA8, 0x1C55D39A, 0x98DA4836,
    0xA163BF05, 0xC2007CB8, 0xECE45B3D, 0x49286651, 0x7C4B1FE6, 0xAE9F2411, 0x5A899FA5, 0xEE386BFB,
    0xF406B7ED, 0x0BFF5CB6, 0xA637ED6B, 0xF44C42E9, 0x625E7EC6, 0xE485B576, 0x6D51C245, 0x4FE1356D,
    0xF25F1437, 0x302B0A6D, 0xCD3A431B, 0xEF9519B3, 0x8E3404DD, 0x514A0879, 0x3B139B22, 0x020BBEA6,
    0x8A67CC74, 0x29024E08, 0x80DC1CD1, 0xC4C6628B, 0x2168C234, 0xC90FDAA2, 0xFFFFFFFF, 0xFFFFFFFF
};

#endif

static BN_BigNum g_bnRfc3526Prime2048 = {
    false,
    (uint32_t)sizeof(RFC3526_PRIME_2048) / sizeof(RFC3526_PRIME_2048[0]),
    (uint32_t)sizeof(RFC3526_PRIME_2048) / sizeof(RFC3526_PRIME_2048[0]),
    0,
    (BN_UINT *)(uintptr_t)RFC3526_PRIME_2048
};

static BN_BigNum g_bnRfc3526Prime3072 = {
    false,
    (uint32_t)sizeof(RFC3526_PRIME_3072) / sizeof(RFC3526_PRIME_3072[0]),
    (uint32_t)sizeof(RFC3526_PRIME_3072) / sizeof(RFC3526_PRIME_3072[0]),
    0,
    (BN_UINT *)(uintptr_t)RFC3526_PRIME_3072
};

static BN_BigNum g_bnRfc3526Prime4096 = {
    false,
    (uint32_t)sizeof(RFC3526_PRIME_4096) / sizeof(RFC3526_PRIME_4096[0]),
    (uint32_t)sizeof(RFC3526_PRIME_4096) / sizeof(RFC3526_PRIME_4096[0]),
    0,
    (BN_UINT *)(uintptr_t)RFC3526_PRIME_4096
};

static BN_BigNum *GetBnConst(BN_BigNum *outConst, BN_BigNum *inConst)
{
    if (outConst == NULL) {
        return BN_Dup(inConst);
    } else {
        if (BN_Copy(outConst, inConst) != CRYPT_SUCCESS) {
            return NULL;
        }
        return outConst;
    }
}

BN_BigNum *BN_GetRfc3526Prime(BN_BigNum *r, uint32_t len)
{
    switch (len) {
        case 2048: // return 2048-bit MODP bn
            return GetBnConst(r, &g_bnRfc3526Prime2048);
        case 3072: // return 3072-bit MODP bn
            return GetBnConst(r, &g_bnRfc3526Prime3072);
        case 4096: // return 4096-bit MODP bn
            return GetBnConst(r, &g_bnRfc3526Prime4096);
        default:
            return NULL;
    }
}
#endif /* HITLS_CRYPTO_BN_PRIME_RFC3526 */
